/* list.c -- 支持链表操作的函数 */
#include <stdio.h>
#include <stdlib.h>
#include "List.h"

/* 局部函数原型
 * 存储类别说明符 static 表明该函数具有内部链接
 */
static void CopyToNode(Item item, Node * pnode);

/* 接口函数
 * 把链表设置为空
 */
void InitializeList(List * plist)
{
    * plist = NULL;
}

/* 如果链表为空：返回 true
 *
 */
bool ListIsEmpty(const List * plist)
{
    if (*plist == NULL)
        return true;
    else
        return false;
}

/* 如果链表已满，返回 true
 *
 */
bool ListIsFull(const List * plist)
{
    Node * pt;
    bool full;
    
    pt = (Node *) malloc(sizeof(Node));
    if (pt == NULL)
        full = true;
    else
        full = false;
    free(pt);
    
    return full;
}

/* 返回节点的数量
 */
unsigned int ListItemCount(const List * plist)
{
    unsigned int count = 0;//链表项的总计
    Node * pnode = *plist;//设置链表的开始
    
    while (pnode != NULL)
    {
        ++count;
        pnode = pnode->next;//设置下一个节点
    }
    
    return count;
}

/* 操作：在链表末尾添加项
 *      item 待添加至链表的项
 *      plist指向一个已初始化的链表
 * 返回值：如果添加成功，该函数返回 true；否则返回 false
 */
bool AddItem(Item item, List * plist)
{
    Node * pnew;
    Node * scan = *plist;
    
    pnew = (Node *) malloc(sizeof(Node));//首先为新节点分配内存空间
    
    /* 无法确定用户是否在给链表添加项时：调用 ListIsFull() 函数
     * 在此处检查内存是否分配成功
     */
    if (pnew == NULL)
        return false;     //分配内存失败时返回函数
    
    //分配内存成功时
    CopyToNode(item, pnew);//将项 item 拷贝至新节点中
    pnew->next = NULL;//将节点的 next 设置为 NULL ，表明是链表中的最后一个节点
    if (scan == NULL)//如果是空链表
        *plist = pnew;//将 pnew 放在链表开头
    else
    {
        while (scan->next != NULL)
            scan = scan->next;//找到链表末尾
        scan->next = pnew;//将 pnew 添加到链表末尾
    }
    return true;
}

/* 访问每个节点并执行 pfun 指向的函数
 */
void Traverse  (const List * plist, void (* pfun)(Item item) )
{
    Node * pnode = *plist;//设置链表的开始
    
    while (pnode != NULL)
    {
        (*pfun)(pnode->item);//把链表用于函数中的项
        pnode = pnode->next;//前进到下一项
    }
}

/* 释放由 malloc() 分配的内存
 * 设置链表指针为 NULL
 */
void EmptyTheList(List * plist)
{
    Node * psave;
    
    while (*plist != NULL)
    {
        psave = (*plist)->next; //保存下一个节点的地址
        free(*plist);           //释放当前节点
        *plist = psave;         //前进至下一个节点
    }
}

/* 局部函数定义
 * 把一个项拷贝到节点中
 */
static void CopyToNode(Item item, Node * pnode)
{
    pnode->item = item;  //拷贝结构
}
